<script setup lang="tsx">
import { computed, ref } from 'vue';
import type { Ref } from 'vue';
import { NButton, NCard, NDataTable, NTag, NInput, NSpace } from 'naive-ui';
import { useBoolean } from '@sa/hooks';
import {
  fetchGetAllPages,
  fetchGetMenuList,
  fetchGetMenuTree,
  fetchAddMenu,
  fetchUpdateMenu,
  fetchDeleteMenu,
  fetchBatchDeleteMenu,
  fetchUpdateMenuOrder
} from '@/service/api';
import { useAppStore } from '@/store/modules/app';
import { useTableOperate } from '@/hooks/common/table';
import { $t } from '@/locales';
import { yesOrNoRecord } from '@/constants/common';
import { enableStatusRecord, menuTypeRecord } from '@/constants/business';
import SvgIcon from '@/components/custom/svg-icon.vue';
import TableHeaderOperation from '@/components/advanced/table-header-operation.vue';
import MenuOperateModal, { type OperateType } from './modules/menu-operate-modal.vue';

const appStore = useAppStore();

const { bool: visible, setTrue: openModal } = useBoolean();

const wrapperRef = ref<HTMLElement | null>(null);

// 数据状态
const loading = ref(false);
const data = ref<Api.SystemManage.Menu[]>([]);
const searchKeyword = ref('');

// 过滤后的数据
const filteredData = computed(() => {
  if (!searchKeyword.value) {
    return data.value;
  }

  const keyword = searchKeyword.value.toLowerCase();

  function filterMenus(menus: Api.SystemManage.Menu[]): Api.SystemManage.Menu[] {
    const result: Api.SystemManage.Menu[] = [];

    for (const menu of menus) {
      const matchesKeyword =
        menu.menuName.toLowerCase().includes(keyword) ||
        menu.routeName?.toLowerCase().includes(keyword) ||
        menu.routePath?.toLowerCase().includes(keyword) ||
        (menu.i18nKey && $t(menu.i18nKey).toLowerCase().includes(keyword));

      if (matchesKeyword) {
        result.push(menu);
      } else if (menu.children && menu.children.length > 0) {
        const filteredChildren = filterMenus(menu.children);
        if (filteredChildren.length > 0) {
          result.push({
            ...menu,
            children: filteredChildren
          });
        }
      }
    }

    return result;
  }

  return filterMenus(data.value);
});

// 列定义
const columns = computed<NaiveUI.TableColumn<Api.SystemManage.Menu>[]>(() => [
  {
    type: 'selection',
    align: 'center',
    width: 48
  },
  {
    key: 'id',
    title: $t('page.manage.menu.id'),
    align: 'center',
    tree: true
  },
  {
    key: 'menuType',
    title: $t('page.manage.menu.menuType'),
    align: 'center',
    width: 80,
    render: (row: Api.SystemManage.Menu) => {
      const tagMap: Record<Api.SystemManage.MenuType, NaiveUI.ThemeColor> = {
        '1': 'default',
        '2': 'primary'
      };

      const label = $t(menuTypeRecord[row.menuType]);

      return <NTag type={tagMap[row.menuType]}>{label}</NTag>;
    }
  },
  {
    key: 'menuName',
    title: $t('page.manage.menu.menuName'),
    align: 'left',
    minWidth: 200,
    render: (row: Api.SystemManage.Menu) => {
      const { i18nKey, menuName } = row;

      const label = i18nKey ? $t(i18nKey) : menuName;

      return <span>{label}</span>;
    }
  },
  {
    key: 'icon',
    title: $t('page.manage.menu.icon'),
    align: 'center',
    width: 60,
    render: (row: Api.SystemManage.Menu) => {
      const icon = row.iconType === '1' ? row.icon : undefined;
      const localIcon = row.iconType === '2' ? row.icon : undefined;
      return (
        <div class="flex-center">
          <SvgIcon icon={icon} localIcon={localIcon} class="text-icon" />
        </div>
      );
    }
  },
  {
    key: 'routeName',
    title: $t('page.manage.menu.routeName'),
    align: 'center',
    minWidth: 120
  },
  {
    key: 'routePath',
    title: $t('page.manage.menu.routePath'),
    align: 'center',
    minWidth: 120
  },
  {
    key: 'status',
    title: $t('page.manage.menu.menuStatus'),
    align: 'center',
    width: 80,
    render: row => {
      if (row.status === null) {
        return null;
      }

      const tagMap: Record<Api.Common.EnableStatus, NaiveUI.ThemeColor> = {
        1: 'success',
        2: 'warning'
      };

      const label = $t(enableStatusRecord[row.status]);

      return <NTag type={tagMap[row.status]}>{label}</NTag>;
    }
  },
  {
    key: 'hideInMenu',
    title: $t('page.manage.menu.hideInMenu'),
    align: 'center',
    width: 80,
    render: (row: Api.SystemManage.Menu) => {
      const hide: CommonType.YesOrNo = row.hideInMenu ? 'Y' : 'N';

      const tagMap: Record<CommonType.YesOrNo, NaiveUI.ThemeColor> = {
        Y: 'error',
        N: 'default'
      };

      const label = $t(yesOrNoRecord[hide]);

      return <NTag type={tagMap[hide]}>{label}</NTag>;
    }
  },
  {
    key: 'parentId',
    title: $t('page.manage.menu.parentId'),
    width: 90,
    align: 'center'
  },
  {
    key: 'orderNum',
    title: $t('page.manage.menu.order'),
    align: 'center',
    width: 60
  },
  {
    key: 'operate',
    title: $t('common.operate'),
    align: 'center',
    width: 230,
    render: (row: Api.SystemManage.Menu) => (
      <div class="flex-center justify-end gap-8px">
        {row.menuType === '1' && (
          <NButton type="primary" ghost size="small" onClick={() => handleAddChildMenu(row)}>
            {$t('page.manage.menu.addChildMenu')}
          </NButton>
        )}
        <NButton type="primary" ghost size="small" onClick={() => handleEdit(row)}>
          {$t('common.edit')}
        </NButton>
        <NButton type="error" ghost size="small" onClick={() => showDeleteConfirm(row.id)}>
          {$t('common.delete')}
        </NButton>
      </div>
    )
  }
]);

// 列选择状态
const columnChecks = ref<NaiveUI.TableColumnCheck[]>([
  { key: '__selection__', title: $t('common.check'), checked: true },
  { key: 'id', title: $t('page.manage.menu.id'), checked: true },
  { key: 'menuType', title: $t('page.manage.menu.menuType'), checked: true },
  { key: 'menuName', title: $t('page.manage.menu.menuName'), checked: true },
  { key: 'icon', title: $t('page.manage.menu.icon'), checked: true },
  { key: 'routeName', title: $t('page.manage.menu.routeName'), checked: true },
  { key: 'routePath', title: $t('page.manage.menu.routePath'), checked: true },
  { key: 'status', title: $t('page.manage.menu.menuStatus'), checked: true },
  { key: 'hideInMenu', title: $t('page.manage.menu.hideInMenu'), checked: true },
  { key: 'parentId', title: $t('page.manage.menu.parentId'), checked: true },
  { key: 'orderNum', title: $t('page.manage.menu.order'), checked: true },
  { key: 'operate', title: $t('common.operate'), checked: true }
]);

// 获取数据
async function getData() {
  loading.value = true;
  try {
    const { error, data: responseData } = await fetchGetMenuList();

    if (!error && responseData) {
      // 根据API类型定义，MenuList是分页格式
      if (responseData.records && Array.isArray(responseData.records)) {
        data.value = responseData.records;
      } else if (Array.isArray(responseData)) {
        // 如果直接返回数组格式
        data.value = responseData;
      } else {
        // 尝试其他可能的数据格式
        const anyData = responseData as any;
        if (anyData.data && Array.isArray(anyData.data)) {
          data.value = anyData.data;
        } else if (anyData.list && Array.isArray(anyData.list)) {
          data.value = anyData.list;
        } else {
          window.$message?.error('菜单数据格式不正确，请联系管理员');
          data.value = [];
        }
      }
    } else {
      const errorMsg = (responseData as any)?.message || '获取菜单数据失败';
      window.$message?.error(errorMsg);
      data.value = [];
    }

    // 预加载图标
    await preloadIcons();
  } catch (error) {
    console.error('获取菜单数据异常:', error);
    window.$message?.error('获取菜单数据异常，请检查网络连接');
    data.value = [];
  } finally {
    loading.value = false;
  }
}

// 预加载图标函数
async function preloadIcons() {
  const iconNames = new Set<string>();

  // 收集所有图标名称
  function collectIcons(menus: Api.SystemManage.Menu[]) {
    menus.forEach(menu => {
      if (menu.icon && menu.iconType === '1') {
        iconNames.add(menu.icon);
      }
      if (menu.children && menu.children.length > 0) {
        collectIcons(menu.children);
      }
    });
  }

  collectIcons(data.value);

  // 这里可以添加图标预加载逻辑
  // 由于 Iconify 会自动处理图标加载，我们只需要确保网络连接正常
}

const { checkedRowKeys, onBatchDeleted, onDeleted } = useTableOperate(data, () => getData());

const operateType = ref<OperateType>('add');

function handleAdd() {
  operateType.value = 'add';
  openModal();
}

async function handleBatchDelete() {
  if (checkedRowKeys.value.length === 0) {
    window.$message?.warning('请选择要删除的菜单');
    return;
  }

  const loadingMessage = window.$message?.loading('正在删除菜单...', { duration: 0 });

  try {
    const { error, data } = await fetchBatchDeleteMenu(checkedRowKeys.value.map(key => Number(key)));

    if (!error) {
      window.$message?.success($t('common.deleteSuccess'));
      onBatchDeleted();
      await getData();
    } else {
      window.$message?.error((data as any)?.message || '删除菜单失败，请重试');
    }
  } catch (err) {
    window.$message?.error('删除菜单时发生异常，请检查网络连接');
  } finally {
    loadingMessage?.destroy();
  }
}

async function handleDelete(id: number) {
  const loadingMessage = window.$message?.loading('正在删除菜单...', { duration: 0 });

  try {
    const { error, data } = await fetchDeleteMenu(id);

    if (!error) {
      window.$message?.success($t('common.deleteSuccess'));
      onDeleted();
      await getData();
    } else {
      window.$message?.error((data as any)?.message || '删除菜单失败，请重试');
    }
  } catch (err) {
    window.$message?.error('删除菜单时发生异常，请检查网络连接');
  } finally {
    loadingMessage?.destroy();
  }
}

// 显示删除确认对话框
function showDeleteConfirm(id: number) {
  window.$dialog?.warning({
    title: $t('common.tip'),
    content: $t('common.confirmDelete'),
    positiveText: $t('common.confirm'),
    negativeText: $t('common.cancel'),
    onPositiveClick: () => {
      handleDelete(id);
    }
  });
}

/** the edit menu data or the parent menu data when adding a child menu */
const editingData: Ref<Api.SystemManage.Menu | null> = ref(null);

function handleEdit(item: Api.SystemManage.Menu) {
  operateType.value = 'edit';
  editingData.value = { ...item };

  openModal();
}

function handleAddChildMenu(item: Api.SystemManage.Menu) {
  operateType.value = 'addChild';

  editingData.value = { ...item };

  openModal();
}

const allPages = ref<string[]>([]);

async function getAllPages() {
  const { data: pages } = await fetchGetAllPages();
  allPages.value = pages || [];
}

function handleModalSubmitted() {
  getData();
}

// 处理菜单排序
async function handleMenuSort(sortedData: Api.SystemManage.Menu[]) {
  const updateItems: { id: number; orderNum: number }[] = [];

  function collectSortOrder(menus: Api.SystemManage.Menu[], startOrder = 1) {
    menus.forEach((menu, index) => {
      const newOrder = startOrder + index;
      if (menu.orderNum !== newOrder) {
        updateItems.push({ id: menu.id, orderNum: newOrder });
      }

      if (menu.children && menu.children.length > 0) {
        collectSortOrder(menu.children, newOrder * 100);
      }
    });
  }

  collectSortOrder(sortedData);

  if (updateItems.length > 0) {
    const loadingMessage = window.$message?.loading('正在更新菜单排序...', { duration: 0 });

    try {
      const { error } = await fetchUpdateMenuOrder(updateItems);

      if (!error) {
        window.$message?.success('菜单排序更新成功');
        await getData();
      } else {
        window.$message?.error('菜单排序更新失败，请重试');
      }
    } catch (err) {
      window.$message?.error('更新菜单排序时发生异常');
    } finally {
      loadingMessage?.destroy();
    }
  }
}

function init() {
  getAllPages();
  getData();
}

// init
init();
</script>

<template>
  <div ref="wrapperRef" class="flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
    <NCard :title="$t('page.manage.menu.title')" :bordered="false" size="small" class="sm:flex-1-hidden card-wrapper">
      <template #header-extra>
        <NSpace :size="16" align="center">
          <NInput
            v-model:value="searchKeyword"
            :placeholder="$t('common.keywordSearch')"
            clearable
            class="w-240px"
          >
            <template #prefix>
              <icon-ic-round-search class="text-icon" />
            </template>
          </NInput>
          <TableHeaderOperation
            v-model:columns="columnChecks"
            :disabled-delete="checkedRowKeys.length === 0"
            :loading="loading"
            @add="handleAdd"
            @delete="handleBatchDelete"
            @refresh="getData"
          />
        </NSpace>
      </template>
      <NDataTable
        v-model:checked-row-keys="checkedRowKeys"
        :columns="columns"
        :data="filteredData"
        size="small"
        :flex-height="!appStore.isMobile"
        :scroll-x="1088"
        :loading="loading"
        :row-key="row => row.id"
        children-key="children"
        :indent="20"
        default-expand-all
        expand-on-click
        class="sm:h-full"
      />
      <MenuOperateModal
        v-model:visible="visible"
        :operate-type="operateType"
        :row-data="editingData"
        :all-pages="allPages"
        @submitted="handleModalSubmitted"
      />
    </NCard>
  </div>
</template>

<style scoped></style>
